home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / anticamp.zip / ANTICAMP.QC next >
Text File  |  1996-10-13  |  8KB  |  249 lines

  1. /*
  2. =====================================================
  3. AntiCamper camper-killing mod v1.0
  4. by Harlequin (dtebben@alumni.caltech.edu)
  5. =====================================================
  6.  
  7. Kills campers by having items check their immediate
  8. vicinity.  If the same person is there for three
  9. consecutive think times, about 20 seconds total,
  10. make them regret it.
  11.  
  12. */
  13.  
  14. void() ItemFindCampers;
  15. void() SUB_regen;
  16.  
  17.  
  18. //#Harlequin#  Nukes the bastard.  Gets snipers too.
  19. void(entity camper, entity campitem) KillCamper =
  20. {
  21.     if (camper.deadflag >= DEAD_DEAD)  //#Harlequin#  Otherwise you can get stuck after death
  22.         return;
  23.  
  24. //#Harlequin#  Take away armor, invisibility, and invulnerability
  25.     camper.armortype = 0;
  26.     camper.armorvalue = 0;
  27.     if (camper.invisible_finished)
  28.     {
  29.         camper.items = camper.items - IT_INVISIBILITY;
  30.         camper.invisible_finished = 0;
  31.         camper.invisible_time = 0;
  32.     }
  33.     if (camper.invincible_finished)
  34.     {
  35.         camper.items = camper.items - IT_INVULNERABILITY;
  36.         camper.invincible_time = 0;
  37.         camper.invincible_finished = 0;
  38.     }
  39.  
  40. //#Harlequin#  Smack them down to 1 health
  41.     T_Damage(camper, world, world, camper.health - 1);
  42.  
  43. //#Harlequin#  Paralyze them
  44.     camper.attack_finished = time + 50000;
  45.     camper.pausetime = time + 50000;
  46.  
  47. //#Harlequin#  Tell everybody where they are
  48.     bprint(camper.netname);
  49.     if (campitem.targetname == "sniper_detector")
  50.     {
  51.         bprint(" IS CAMPING AT ");  //#Harlequin# 'is sniping at' is ambiguous -- sounds like they're shooting at something
  52.         bprint(campitem.message);
  53.     }
  54.     else
  55.     {
  56.         bprint(" IS CAMPING AT THE ");
  57.         bprint(campitem.CAMPPOS);
  58.     }
  59.     bprint("!\n");
  60.  
  61. //#Harlequin#  Take away 2 frags
  62.     camper.frags = camper.frags - 2;
  63. };
  64.  
  65.  
  66. //#Harlequin#  GetLongDistance determines the distance at which items
  67. //will issue warnings if they have an unbroken line-of-sight to the
  68. //player.  On levels with lots of open spaces, for example e1m8, this
  69. //value should be set lower than the default 800, to avoid detecting
  70. //innocent (well, non-camping anyway) players.  To give you an idea
  71. //of how far 800 units is, it's about the distance from the rocket
  72. //launcher of e1m1 to the L-bend in the catwalk leading there.
  73. //Setting longdist to 1 in a map disables AntiCamper for that map.
  74. //Do NOT set it to zero or you'll slow down the server.
  75. float() GetLongDistance =
  76. {
  77.     local float dist;
  78.  
  79. //#Harlequin#  Defaults to 800
  80.     dist = 800;
  81.  
  82. //#Harlequin#  Put map names and LOS-distances here, in the following format:
  83.     if (world.model == "maps/e1m8.bsp")
  84.         dist = 400;
  85.  
  86. //#Harlequin#  Keep this as the last line of the function
  87.     return dist;
  88. };
  89.  
  90.  
  91. //#Harlequin#  GetShortDistance is the distance at which items will
  92. //see players if they do *not* have line-of-sight.  This is necessary
  93. //to prevent people from ducking around corners to defeat the mod.
  94. //On small levels, where it's easy to be "seen" through walls by
  95. //camper-sensitive items, set this lower than the default 250.  On
  96. //camper-heavy maps with out-of-the-way weapons, setting this value
  97. //higher is useful.
  98. float() GetShortDistance =
  99. {
  100.     local float dist;
  101.     
  102. //#Harlequin#  Defaults to 250
  103.     dist = 250;
  104.  
  105. //#Harlequin#  Put map names and no-LOS distances here.  Note that it
  106. //is possible to change both longdist and shortdist on a single map,
  107. //but shortdist will never be longer than longdist.
  108.     if (world.model == "maps/e1m8.bsp")
  109.         dist = 200;
  110.  
  111. //#Harlequin#  Keep this as the last line of the function
  112.     return dist;
  113. };
  114.  
  115.  
  116. //#Harlequin#  GetThinkTimes returns an average length between camper
  117. //checks, in seconds, for every item on the level.  It will actually
  118. //vary between (thinktime - 0.5) and (thinktime + 0.5) sec.
  119. float() GetThinkTimes =
  120. {
  121.     local float ttimes;
  122.  
  123. //#Harlequin#  Defaults to 8
  124.     ttimes = 8;
  125.  
  126. //#Harlequin#  Add your own map names and think times below
  127.     if (world.model == "maps/e1m8.bsp")
  128.         ttimes = 6;
  129.  
  130. //#Harlequin#  Leave the following line as the last one
  131.     return ttimes;
  132. };
  133.  
  134.  
  135. //#Harlequin#  ItemFindCampers is the heart of the mod.  It checks
  136. //a sphere of radius 'longdist' around itself, and if it finds any
  137. //players in its line of sight it "tags" them (it also tags players
  138. //that are not within LOS, but are less than 'shortdist' units away).
  139. //If they're still there after one think time (~8 seconds), it warns
  140. //them.  If they're still there after two think times, it kills them.
  141. //Thus from the time someone starts camping, the average total time
  142. //for an item to see them, warn them, and nuke them is 20 seconds.
  143. void() ItemFindCampers = 
  144. {
  145.     local entity head;
  146.  
  147. //#Harlequin#  Get 'longdist' LOS warning distance & 'shortdist' no-LOS warning distance, map-dependent
  148.     if (!longdist)
  149.         longdist = GetLongDistance();
  150.     if (!shortdist)
  151.         shortdist = GetShortDistance();
  152.  
  153. //#Harlequin#  Get think times
  154.     if (!thinktimes)
  155.         thinktimes = GetThinkTimes();
  156.  
  157. //#Harlequin#  Think times are somewhat random so it's harder to second-guess, also improves speed
  158.     self.think = ItemFindCampers;
  159.     self.nextthink = time + (thinktimes - 0.5) + random();
  160.  
  161. //#Harlequin#  Respawn item if it's time
  162.     if (self.RESPAWN_TIME && (self.RESPAWN_TIME <= time))
  163.     {
  164.         SUB_regen();
  165.         self.RESPAWN_TIME = 0;
  166.     }
  167.  
  168. //#Harlequin#  Looks for players within 'longdist' units of itself
  169.     head = findradius(self.origin, longdist);
  170.     while (head)
  171.     {
  172. //#Harlequin#  Don't pick on non-players, dead players, or camperkilled players.  The CAMPER_TIME part is there to prevent items from cancelling each other out.
  173.         if ((head.classname == "player") && (!(head.deadflag >= DEAD_DEAD)) && (head.pausetime < time + 100) && (head.CAMPER_TIME < time + (thinktimes / 2)))
  174.         {
  175. //#Harlequin#  Checks for line-of-sight, or less than 'shortdist' distance -- checks origin + '0 0 20' because origins are at ground level
  176.             traceline((self.origin + '0 0 20'), (head.origin + '0 0 20'), TRUE, self);
  177.             if ( (trace_fraction == 1) || (vlen(head.origin - self.origin) < shortdist) )
  178.             {
  179.                 if (head.CAMPER_WARNING_ITEM2 == self) //#Harlequin# They're camping, kill them
  180.                     KillCamper(head, self);
  181.                 else if (head.CAMPER_WARNING_ITEM1 == self) //#Harlequin#  Warn the player
  182.                 {
  183. //#Harlequin#  Camper warning makes screen flash and prints message
  184.                     head.CAMPER_WARNING_ITEM2 = self;
  185.                     stuffcmd(head, "bf\n");
  186.                     sprint(head, "**CAMPER WARNING FROM ");
  187.                     sprint(head, self.CAMPPOS);
  188.                     sprint(head, "\n");
  189. //#Harlequin#  Add two slashes to the next line to disable camper-warning sounds
  190.                     sound(head, CHAN_BODY, "dog/dsight.wav", 1, ATTN_NORM);
  191.                     head.CAMPER_TIME = time + thinktimes + 1;
  192.                 }
  193.                 else //#Harlequin#  Notice the player 1st time
  194.                 {
  195.                     head.CAMPER_WARNING_ITEM1 = self;
  196.                     head.CAMPER_TIME = time + thinktimes + 1;
  197.                 }
  198.             }
  199.         }
  200.     head = head.chain;
  201.     }
  202. };
  203.  
  204.  
  205. //#Harlequin#  Substantially the same as ItemFindCampers.  It uses its
  206. //"speed" field as a longdist, and its "count" field as a shortdist.
  207. //Note that it computes line of sight from its origin to its target's
  208. //origin + '0 0 20', which lets it see players from about the chest
  209. //down.  Don't put sniper entities on the floor unless it's flat, and
  210. //give them the clearest possible line-of-sight to their surroundings.
  211. void() EntityFindSnipers =
  212. {
  213.     local entity head;
  214.  
  215.     self.think = EntityFindSnipers;
  216.     self.nextthink = time + (self.dmg - 0.5) + random();
  217.  
  218.     head = findradius (self.origin, self.speed);
  219.     while(head)
  220.     {
  221.         if ((head.classname == "player") && (!(head.deadflag >= DEAD_DEAD)) && (head.pausetime < time + 100))
  222.         {
  223.             traceline(self.origin, (head.origin + '0 0 20'), TRUE, self);
  224.             if ( (trace_fraction == 1) || (vlen(head.origin - self.origin) < self.count) )
  225.             {
  226.                 if (head.SNIPER_WARNING_ENTITY2 == self)
  227.                     KillCamper(head, self);
  228.                 else if (head.SNIPER_WARNING_ENTITY1 == self)
  229.                 {
  230.                     head.SNIPER_WARNING_ENTITY2 = self;
  231.                     stuffcmd(head, "bf\n");
  232.                     sprint(head, "**SNIPER WARNING FROM ");
  233.                     sprint(head, self.message);
  234.                     sprint(head, "\n");
  235. //#Harlequin#  Add two slashes to the next line to disable sniper-warning sounds
  236.                     sound(head, CHAN_BODY, "ogre/ogwake.wav", 1, ATTN_NORM);
  237.                     head.SNIPER_TIME = time + self.dmg + 1;
  238.                 }
  239.                 else
  240.                 {
  241.                     head.SNIPER_WARNING_ENTITY1 = self;
  242.                     head.SNIPER_TIME = time + self.dmg + 1;
  243.                 }
  244.             }
  245.         }
  246.     head = head.chain;
  247.     }
  248. };
  249.